From 1a5d043f7918f40bd1ab7e0c66735e3c9a5faed7 Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Fri, 11 Apr 2025 11:33:45 +0200 Subject: [PATCH] fix: do not interrupt sync when cleaning invalid read-only items Signed-off-by: Matthieu Gallien --- src/gui/folder.cpp | 30 --------- src/gui/folder.h | 4 -- src/libsync/discovery.cpp | 15 ++--- src/libsync/filesystem.cpp | 16 ++++- src/libsync/filesystem.h | 5 +- src/libsync/syncengine.cpp | 27 ++++++-- src/libsync/syncengine.h | 4 -- test/testpermissions.cpp | 131 +++++++------------------------------ 8 files changed, 67 insertions(+), 165 deletions(-) diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index f89dab9c5..62aa980cd 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -107,8 +107,6 @@ Folder::Folder(const FolderDefinition &definition, connect(_engine.data(), &SyncEngine::aboutToRemoveAllFiles, this, &Folder::slotAboutToRemoveAllFiles); - connect(_engine.data(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - this, &Folder::slotNeedToRemoveRemnantsReadOnlyFolders); connect(_engine.data(), &SyncEngine::transmissionProgress, this, &Folder::slotTransmissionProgress); connect(_engine.data(), &SyncEngine::itemCompleted, this, &Folder::slotItemCompleted); @@ -1723,34 +1721,6 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, std::functio msgBox->open(); } -void Folder::slotNeedToRemoveRemnantsReadOnlyFolders(const QList &folders, - const QString &localPath, - std::function callback) -{ - auto listOfFolders = QStringList{}; - for (const auto &oneFolder : folders) { - listOfFolders.push_back(oneFolder->_file); - } - - qCInfo(lcFolder()) << "will delete invalid read-only folders:" << listOfFolders.join(", "); - - setSyncPaused(true); - for(const auto &oneFolder : folders) { - const auto fileInfo = QFileInfo{localPath + oneFolder->_file}; - const auto parentFolderPath = fileInfo.dir().absolutePath(); - const auto parentPermissionsHandler = FileSystem::FilePermissionsRestore{parentFolderPath, FileSystem::FolderPermissions::ReadWrite}; - if (oneFolder->_type == ItemType::ItemTypeDirectory) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } else { - FileSystem::remove(localPath + oneFolder->_file); - } - } - callback(true); - setSyncPaused(false); - _lastEtag.clear(); - slotScheduleThisFolder(); -} - void Folder::removeLocalE2eFiles() { qCDebug(lcFolder) << "Removing local E2EE files"; diff --git a/src/gui/folder.h b/src/gui/folder.h index 741ce76b1..f66d4c81b 100644 --- a/src/gui/folder.h +++ b/src/gui/folder.h @@ -336,10 +336,6 @@ public slots: // connected to the corresponding signals in the SyncEngine void slotAboutToRemoveAllFiles(OCC::SyncFileItem::Direction, std::function callback); - void slotNeedToRemoveRemnantsReadOnlyFolders(const QList &folders, - const QString &localPath, - std::function callback); - /** * Starts a sync operation * diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index 4c0dfa151..b3fedf6da 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -1867,16 +1867,14 @@ bool ProcessDirectoryJob::checkPermissions(const OCC::SyncFileItemPtr &item) // No permissions set return true; } else if (item->isDirectory() && !perms.hasPermission(RemotePermissions::CanAddSubDirectories)) { - qCWarning(lcDisco) << "checkForPermission: ERROR" << item->_file; - item->_instruction = CSYNC_INSTRUCTION_ERROR; + qCWarning(lcDisco) << "checkForPermission: Not allowed because you don't have permission to add subfolders to that folder:" << item->_file; + item->_instruction = CSYNC_INSTRUCTION_IGNORE; item->_errorString = tr("Not allowed because you don't have permission to add subfolders to that folder"); - const auto localPath = QString{_discoveryData->_localDir + item->_file}; - qCWarning(lcDisco) << "unexpected new folder in a read-only folder will be made read-write" << localPath; emit _discoveryData->remnantReadOnlyFolderDiscovered(item); return false; } else if (!item->isDirectory() && !perms.hasPermission(RemotePermissions::CanAddFile)) { - qCWarning(lcDisco) << "checkForPermission: ERROR" << item->_file; - item->_instruction = CSYNC_INSTRUCTION_ERROR; + qCWarning(lcDisco) << "checkForPermission: Not allowed because you don't have permission to add files in that folder:" << item->_file; + item->_instruction = CSYNC_INSTRUCTION_IGNORE; item->_errorString = tr("Not allowed because you don't have permission to add files in that folder"); emit _discoveryData->remnantReadOnlyFolderDiscovered(item); return false; @@ -2072,11 +2070,10 @@ int ProcessDirectoryJob::processSubJobs(int nbJobs) if (perms.isNull()) { // No permissions set } else if (_dirItem->isDirectory() && !perms.hasPermission(RemotePermissions::CanAddSubDirectories)) { - qCWarning(lcDisco) << "checkForPermission: ERROR" << _dirItem->_file; - _dirItem->_instruction = CSYNC_INSTRUCTION_ERROR; + qCWarning(lcDisco) << "checkForPermission: Not allowed because you don't have permission to add subfolders to that folder: " << _dirItem->_file; + _dirItem->_instruction = CSYNC_INSTRUCTION_IGNORE; _dirItem->_errorString = tr("Not allowed because you don't have permission to add subfolders to that folder"); const auto localPath = QString{_discoveryData->_localDir + _dirItem->_file}; - qCWarning(lcDisco) << "unexpected new folder in a read-only folder will be made read-write" << localPath; emit _discoveryData->remnantReadOnlyFolderDiscovered(_dirItem); } diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp index 59f375ed2..5371ae35a 100644 --- a/src/libsync/filesystem.cpp +++ b/src/libsync/filesystem.cpp @@ -254,9 +254,13 @@ qint64 FileSystem::getSize(const QString &filename) } // Code inspired from Qt5's QDir::removeRecursively -bool FileSystem::removeRecursively(const QString &path, const std::function &onDeleted, QStringList *errors) +bool FileSystem::removeRecursively(const QString &path, const std::function &onDeleted, QStringList *errors, const std::function &onError) { - FileSystem::setFolderPermissions(path, FileSystem::FolderPermissions::ReadWrite); + if (!FileSystem::setFolderPermissions(path, FileSystem::FolderPermissions::ReadWrite)) { + if (onError) { + onError(path, true); + } + } bool allRemoved = true; QDirIterator di(path, QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot); @@ -269,7 +273,7 @@ bool FileSystem::removeRecursively(const QString &path, const std::functionappend(QCoreApplication::translate("FileSystem", "Error removing \"%1\": %2") .arg(QDir::toNativeSeparators(di.filePath()), removeError)); } + if (onError) { + onError(di.filePath(), false); + } qCWarning(lcFileSystem) << "Error removing " << di.filePath() << ':' << removeError; } } @@ -305,6 +312,9 @@ bool FileSystem::removeRecursively(const QString &path, const std::functionappend(QCoreApplication::translate("FileSystem", "Could not remove folder \"%1\"") .arg(QDir::toNativeSeparators(path))); } + if (onError) { + onError(di.filePath(), false); + } qCWarning(lcFileSystem) << "Error removing folder" << path; } } diff --git a/src/libsync/filesystem.h b/src/libsync/filesystem.h index e0439b8f5..26c999994 100644 --- a/src/libsync/filesystem.h +++ b/src/libsync/filesystem.h @@ -122,8 +122,9 @@ namespace FileSystem { * errors are collected in errors. */ bool OWNCLOUDSYNC_EXPORT removeRecursively(const QString &path, - const std::function &onDeleted = nullptr, - QStringList *errors = nullptr); + const std::function &onDeleted = nullptr, + QStringList *errors = nullptr, + const std::function &onError = nullptr); bool OWNCLOUDSYNC_EXPORT setFolderPermissions(const QString &path, FileSystem::FolderPermissions permissions) noexcept; diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 931911631..e24ce8a30 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -840,7 +840,6 @@ void SyncEngine::slotDiscoveryFinished() if (!_remnantReadOnlyFolders.isEmpty()) { handleRemnantReadOnlyFolders(); - return; } finishSync(); @@ -1169,9 +1168,29 @@ bool SyncEngine::handleMassDeletion() void SyncEngine::handleRemnantReadOnlyFolders() { - promptUserBeforePropagation([this](auto &&callback) { - emit aboutToRemoveRemnantsReadOnlyFolders(_remnantReadOnlyFolders, _localPath, callback); - }); + auto listOfFolders = QStringList{}; + for (const auto &oneFolder : std::as_const(_remnantReadOnlyFolders)) { + listOfFolders.push_back(oneFolder->_file); + } + + qCInfo(lcEngine()) << "will delete invalid read-only folders:" << listOfFolders.join(", "); + + for(const auto &oneFolder : std::as_const(_remnantReadOnlyFolders)) { + const auto fileInfo = QFileInfo{_localPath + oneFolder->_file}; + const auto parentFolderPath = fileInfo.dir().absolutePath(); + slotAddTouchedFile(parentFolderPath); + const auto parentPermissionsHandler = FileSystem::FilePermissionsRestore{parentFolderPath, FileSystem::FolderPermissions::ReadWrite}; + slotAddTouchedFile(_localPath + oneFolder->_file); + + if (oneFolder->_type == ItemType::ItemTypeDirectory) { + const auto deletionCallback = [this] (const QString &deleteItem, bool) { + slotAddTouchedFile(deleteItem); + }; + FileSystem::removeRecursively(_localPath + oneFolder->_file, deletionCallback, nullptr, deletionCallback); + } else { + FileSystem::remove(_localPath + oneFolder->_file); + } + } } template diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h index 76fc99ce7..92ef9fd7a 100644 --- a/src/libsync/syncengine.h +++ b/src/libsync/syncengine.h @@ -190,10 +190,6 @@ signals: */ void aboutToRemoveAllFiles(OCC::SyncFileItem::Direction direction, std::function f); - void aboutToRemoveRemnantsReadOnlyFolders(const QList &folders, - const QString &localPath, - std::function f); - // A new folder was discovered and was not synced because of the confirmation feature void newBigFolder(const QString &folder, bool isExternal); diff --git a/test/testpermissions.cpp b/test/testpermissions.cpp index 5a1345741..8e457e0b6 100644 --- a/test/testpermissions.cpp +++ b/test/testpermissions.cpp @@ -94,14 +94,6 @@ private slots: FakeFolder fakeFolder{ FileInfo() }; QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - qDebug() << "aboutToRemoveRemnantsReadOnlyFolders called"; - Q_UNUSED(folders); - Q_UNUSED(localPath); - callback(false); - }); - // Some of this test depends on the order of discovery. With threading // that order becomes effectively random, but we want to make sure to test // all cases and thus disable threading. @@ -281,14 +273,14 @@ private slots: applyPermissionsFromName(fakeFolder.remoteModifier()); // error: can't upload to readonly - QVERIFY(!fakeFolder.syncOnce()); + QVERIFY(fakeFolder.syncOnce()); assertCsyncJournalOk(fakeFolder.syncJournal()); currentLocalState = fakeFolder.currentLocalState(); //6. - // The file should not exist on the remote, but still be there - QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data")); + // The file should not exist on the remote, and not be there + QVERIFY(!currentLocalState.find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data")); QVERIFY(!fakeFolder.currentRemoteState().find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data")); // remove it so next test succeed. removeReadOnly("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data"); @@ -362,8 +354,8 @@ private slots: //2. move a directory from read to read only (move the directory from previous step) renameReadOnly("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_", "readonlyDirectory_PERM_M_/moved_PERM_CK_" ); - // error: can't upload to readonly! - QVERIFY(!fakeFolder.syncOnce()); + // can't upload to readonly but not an error + QVERIFY(fakeFolder.syncOnce()); currentLocalState = fakeFolder.currentLocalState(); //1. @@ -371,8 +363,8 @@ private slots: QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_" )); // including contents QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" )); - // new still exist - QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/newname_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" )); + // new no longer exists + QVERIFY(!currentLocalState.find("readonlyDirectory_PERM_M_/newname_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" )); // but is not on server: so remove it locally for the future comparison removeReadOnly("readonlyDirectory_PERM_M_/newname_PERM_CK_"); @@ -381,8 +373,8 @@ private slots: QVERIFY(!currentLocalState.find("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_")); // but still on the server: the rename causing an error meant the deletes didn't execute QVERIFY(fakeFolder.currentRemoteState().find("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_")); - // new still there - QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/moved_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" )); + // new no longer exists + QVERIFY(!currentLocalState.find("readonlyDirectory_PERM_M_/moved_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" )); //but not on server removeReadOnly("readonlyDirectory_PERM_M_/moved_PERM_CK_"); fakeFolder.remoteModifier().remove("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_"); @@ -438,13 +430,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - Q_UNUSED(folders) - Q_UNUSED(localPath) - callback(false); - }); - // Some of this test depends on the order of discovery. With threading // that order becomes effectively random, but we want to make sure to test // all cases and thus disable threading. @@ -503,11 +488,11 @@ private slots: SyncFileItemVector discovery; connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToPropagate, this, [&discovery](auto v) { discovery = v; }); ItemCompletedSpy completeSpy(fakeFolder); - QVERIFY(!fakeFolder.syncOnce()); + QVERIFY(fakeFolder.syncOnce()); // if renaming doesn't work, just delete+create QVERIFY(itemInstruction(completeSpy, "norename/file", CSYNC_INSTRUCTION_REMOVE)); - QVERIFY(itemInstruction(completeSpy, "norename/sub", CSYNC_INSTRUCTION_NONE)); + QVERIFY(itemInstruction(completeSpy, "norename/sub", CSYNC_INSTRUCTION_REMOVE)); QVERIFY(discoveryInstruction(discovery, "norename/sub", CSYNC_INSTRUCTION_REMOVE)); QVERIFY(itemInstruction(completeSpy, "norename/file_renamed", CSYNC_INSTRUCTION_NEW)); QVERIFY(itemInstruction(completeSpy, "norename/sub_renamed", CSYNC_INSTRUCTION_NEW)); @@ -516,19 +501,19 @@ private slots: // simiilarly forbidding moves becomes delete+create QVERIFY(itemInstruction(completeSpy, "nomove/file", CSYNC_INSTRUCTION_REMOVE)); - QVERIFY(itemInstruction(completeSpy, "nomove/sub", CSYNC_INSTRUCTION_NONE)); + QVERIFY(itemInstruction(completeSpy, "nomove/sub", CSYNC_INSTRUCTION_REMOVE)); QVERIFY(discoveryInstruction(discovery, "nomove/sub", CSYNC_INSTRUCTION_REMOVE)); // nomove/sub/file is removed as part of the dir QVERIFY(itemInstruction(completeSpy, "allowed/file_moved", CSYNC_INSTRUCTION_NEW)); QVERIFY(itemInstruction(completeSpy, "allowed/sub_moved", CSYNC_INSTRUCTION_NEW)); QVERIFY(itemInstruction(completeSpy, "allowed/sub_moved/file", CSYNC_INSTRUCTION_NEW)); - // when moving to an invalid target, the targets should be an error - QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_ERROR)); - QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_ERROR)); + // when moving to an invalid target, the targets should be ignored + QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_IGNORE)); + QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_IGNORE)); QVERIFY(itemInstruction(completeSpy, "nocreatefile/sub", CSYNC_INSTRUCTION_RENAME)); // TODO: What does a real server say? - QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_ERROR)); - QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_ERROR)); + QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_IGNORE)); + QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_IGNORE)); // and the sources of the invalid moves should be restored, not deleted // (depending on the order of discovery a follow-up sync is needed) @@ -541,12 +526,12 @@ private slots: // A follow-up sync will restore allowed/file and allowed/sub2 and maintain the nocreatedir/file errors completeSpy.clear(); - QVERIFY(!fakeFolder.syncOnce()); + QVERIFY(fakeFolder.syncOnce()); - QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_ERROR)); - QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_ERROR)); - QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_ERROR)); - QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_ERROR)); + QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_NONE)); + QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_NONE)); + QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_NONE)); + QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_NONE)); QVERIFY(itemInstruction(completeSpy, "allowed/file", CSYNC_INSTRUCTION_NEW)); QVERIFY(itemInstruction(completeSpy, "allowed/sub2", CSYNC_INSTRUCTION_NEW)); @@ -564,14 +549,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &lm = fakeFolder.localModifier(); auto &rm = fakeFolder.remoteModifier(); rm.mkdir("forbidden-move"); @@ -623,14 +600,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("readOnlyFolder"); @@ -648,14 +617,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("readWriteFolder"); @@ -674,14 +635,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("testFolder"); @@ -718,14 +671,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("testFolder"); @@ -786,14 +731,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("readOnlyFolder"); @@ -824,14 +761,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("readOnlyFolder"); @@ -864,14 +793,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("readOnlyFolder"); @@ -907,14 +828,6 @@ private slots: { FakeFolder fakeFolder{FileInfo{}}; - QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders, - [&](const QList &folders, const QString &localPath, std::function callback) { - for(const auto &oneFolder : folders) { - FileSystem::removeRecursively(localPath + oneFolder->_file); - } - callback(false); - }); - auto &remote = fakeFolder.remoteModifier(); remote.mkdir("readOnlyFolder"); -- 2.30.2